package org.dxy.trigger.http.service.impl;

import cn.hutool.core.util.EnumUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dxy.api.dto.request.*;
import org.dxy.api.dto.request.workorder.CreateWorkOrderRequest;
import org.dxy.api.dto.response.R;
import org.dxy.api.dto.vo.WorkOrderOptionVo;
import org.dxy.domain.handler.CommandHandler;
import org.dxy.types.enums.WorkOrderStatusEnum;
import org.dxy.types.enums.WorkOrderTypeEnum;
import org.dxy.domain.command.workorder.*;
import org.dxy.infrastructure.persistent.service.WorkOrderViewService;
import org.dxy.infrastructure.persistent.service.MaterialViewService;
import org.dxy.infrastructure.persistent.service.RouteViewService;
import org.dxy.infrastructure.persistent.service.ProductionLineBasicViewService;
import org.dxy.infrastructure.persistent.po.query.WorkOrderViewPo;
import org.dxy.infrastructure.persistent.po.query.MaterialViewPo;
import org.dxy.infrastructure.persistent.po.query.RouteViewPo;
import org.dxy.infrastructure.persistent.po.query.ProductionLineBasicViewPo;
import org.dxy.trigger.http.service.WorkOrderApplicationService;
import org.dxy.domain.service.WorkOrderCodeGenerator;
import org.dxy.types.common.CommandResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 工单应用服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WorkOrderApplicationServiceImpl implements WorkOrderApplicationService {

    private final CommandHandler<CreateWorkOrderCommand, Long> createHandler;
    private final CommandHandler<ReleaseWorkOrderCommand, Void> releaseHandler;
    private final CommandHandler<StartWorkOrderCommand, Void> startHandler;
    private final CommandHandler<SuspendWorkOrderCommand, Void> suspendHandler;
    private final CommandHandler<ResumeWorkOrderCommand, Void> resumeHandler;
    private final CommandHandler<CompleteWorkOrderCommand, Void> completeHandler;
    private final CommandHandler<CloseWorkOrderCommand, Void> closeHandler;
    private final CommandHandler<CancelWorkOrderCommand, Void> cancelHandler;
    private final CommandHandler<UpdateWorkOrderCommand, Void> updateHandler;
    private final CommandHandler<DeleteWorkOrderCommand, Void> deleteHandler;
    private final WorkOrderViewService workOrderViewService;
    private final MaterialViewService materialViewService;
    private final RouteViewService routeViewService;
    private final ProductionLineBasicViewService productionLineViewService;
    private final WorkOrderCodeGenerator codeGenerator;

    @Override
    public R<String> getSuggestedCode() {
        try {
            String suggestedCode = codeGenerator.getSuggestedCode();
            return R.ok(suggestedCode, "获取建议编码成功");
        } catch (Exception e) {
            log.error("获取建议工单编码失败", e);
            return R.fail("获取建议工单编码失败: " + e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R<Long> create(CreateWorkOrderRequest request) {
        try {
            // 将字符串类型的工单类型转换为枚举
            WorkOrderTypeEnum workOrderTypeEnum = EnumUtil.getBy(
                    WorkOrderTypeEnum.class,
                    e -> request.getWorkOrderType().equals(e.getKey())
            );

            if (workOrderTypeEnum == null) {
                return R.fail("无效的工单类型: " + request.getWorkOrderType());
            }

            CreateWorkOrderCommand command = CreateWorkOrderCommand.builder()
                    .workOrderCode(request.getWorkOrderCode())
                    .productId(request.getProductId())
                    .plannedQuantity(request.getPlannedQuantity())
                    .routeId(request.getRouteId())
                    .productionLineId(request.getProductionLineId())
                    .workOrderType(workOrderTypeEnum)
                    .originalWorkOrderId(request.getOriginalWorkOrderId())
                    .plannedStartTime(request.getPlannedStartTime())
                    .plannedEndTime(request.getPlannedEndTime())
                    .build();

            CommandResult<Long> result = createHandler.handle(command);

            if (result.success()) {
                Long workOrderId = result.data();

                // 查询相关名称信息
                String productCode = null;
                String productName = null;
                if (request.getProductId() != null) {
                    MaterialViewPo material = materialViewService.getById(request.getProductId());
                    if (material != null) {
                        productCode = material.getMaterialCode();
                        productName = material.getMaterialName();
                    }
                }

                String routeCode = null;
                String routeName = null;
                if (request.getRouteId() != null) {
                    RouteViewPo route = routeViewService.getById(request.getRouteId());
                    if (route != null) {
                        routeCode = route.getRouteCode();
                        routeName = route.getRouteName();
                    }
                }

                String productionLineCode = null;
                String productionLineName = null;
                if (request.getProductionLineId() != null) {
                    ProductionLineBasicViewPo productionLine = productionLineViewService.getById(request.getProductionLineId());
                    if (productionLine != null) {
                        productionLineCode = productionLine.getLineCode();
                        productionLineName = productionLine.getLineName();
                    }
                }

                // 保存读模型
                WorkOrderViewPo viewEntity = WorkOrderViewPo.builder()
                        .id(workOrderId)
                        .workOrderCode(request.getWorkOrderCode())
                        .workOrderType(request.getWorkOrderType())
                        .productId(request.getProductId())
                        .productCode(productCode)
                        .productName(productName)
                        .routeId(request.getRouteId())
                        .routeCode(routeCode)
                        .routeName(routeName)
                        .productionLineId(request.getProductionLineId())
                        .productionLineCode(productionLineCode)
                        .productionLineName(productionLineName)
                        .plannedQuantity(request.getPlannedQuantity())
                        .completedQuantity(0)
                        .status(WorkOrderStatusEnum.INITIALIZED.getKey())
                        .plannedStartTime(request.getPlannedStartTime())
                        .plannedEndTime(request.getPlannedEndTime())
                        .remarks(request.getRemarks())
                        .build();

                workOrderViewService.save(viewEntity);

                return R.ok(result.data(), result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("创建工单失败", e);
            return R.fail("创建工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> release(Long workOrderId) {
        try {
            ReleaseWorkOrderCommand command = new ReleaseWorkOrderCommand(workOrderId);

            CommandResult<Void> result = releaseHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.RELEASED.getKey());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("下达工单失败, workOrderId={}", workOrderId, e);
            return R.fail("下达工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> start(Long workOrderId) {
        try {
            StartWorkOrderCommand command = new StartWorkOrderCommand(workOrderId);

            CommandResult<Void> result = startHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.STARTED.getKey());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("开始工单失败, workOrderId={}", workOrderId, e);
            return R.fail("开始工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> suspend(Long workOrderId, SuspendWorkOrderRequest request) {
        try {
            SuspendWorkOrderCommand command = new SuspendWorkOrderCommand(workOrderId);

            CommandResult<Void> result = suspendHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.SUSPENDED.getKey());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("暂停工单失败, workOrderId={}", workOrderId, e);
            return R.fail("暂停工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> resume(Long workOrderId) {
        try {
            ResumeWorkOrderCommand command = new ResumeWorkOrderCommand(workOrderId);

            CommandResult<Void> result = resumeHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.STARTED.getKey());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("恢复工单失败, workOrderId={}", workOrderId, e);
            return R.fail("恢复工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> complete(Long workOrderId, CompleteWorkOrderRequest request) {
        try {
            CompleteWorkOrderCommand command = new CompleteWorkOrderCommand(
                    workOrderId,
                    request.getCompletedQuantity()
            );

            CommandResult<Void> result = completeHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态和完成数量
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.COMPLETED.getKey());
                    viewEntity.setCompletedQuantity(request.getCompletedQuantity());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("完成工单失败, workOrderId={}", workOrderId, e);
            return R.fail("完成工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> close(Long workOrderId, CloseWorkOrderRequest request) {
        try {
            CloseWorkOrderCommand command = new CloseWorkOrderCommand(workOrderId);

            CommandResult<Void> result = closeHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.CLOSED.getKey());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("关闭工单失败, workOrderId={}", workOrderId, e);
            return R.fail("关闭工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> cancel(Long workOrderId, CancelWorkOrderRequest request) {
        try {
            CancelWorkOrderCommand command = new CancelWorkOrderCommand(workOrderId);

            CommandResult<Void> result = cancelHandler.handle(command);

            if (result.success()) {
                // 更新读模型状态
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    viewEntity.setStatus(WorkOrderStatusEnum.CANCELLED.getKey());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("取消工单失败, workOrderId={}", workOrderId, e);
            return R.fail("取消工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Page<WorkOrderViewPo>> list(Page<WorkOrderViewPo> page, WorkOrderViewPo query) {
        try {
            LambdaQueryWrapper<WorkOrderViewPo> wrapper = new LambdaQueryWrapper<>();

            // 动态拼接查询条件
            if (StringUtils.isNotBlank(query.getWorkOrderCode())) {
                wrapper.like(WorkOrderViewPo::getWorkOrderCode, query.getWorkOrderCode());
            }

            if (StringUtils.isNotBlank(query.getWorkOrderType())) {
                wrapper.eq(WorkOrderViewPo::getWorkOrderType, query.getWorkOrderType());
            }

            if (StringUtils.isNotBlank(query.getStatus())) {
                wrapper.eq(WorkOrderViewPo::getStatus, query.getStatus());
            }

            if (StringUtils.isNotBlank(query.getProductCode())) {
                wrapper.like(WorkOrderViewPo::getProductCode, query.getProductCode());
            }

            if (StringUtils.isNotBlank(query.getRouteCode())) {
                wrapper.eq(WorkOrderViewPo::getRouteCode, query.getRouteCode());
            }

            if (StringUtils.isNotBlank(query.getProductionLineCode())) {
                wrapper.eq(WorkOrderViewPo::getProductionLineCode, query.getProductionLineCode());
            }

            if (query.getProductId() != null) {
                wrapper.eq(WorkOrderViewPo::getProductId, query.getProductId());
            }

            if (query.getRouteId() != null) {
                wrapper.eq(WorkOrderViewPo::getRouteId, query.getRouteId());
            }

            if (query.getProductionLineId() != null) {
                wrapper.eq(WorkOrderViewPo::getProductionLineId, query.getProductionLineId());
            }

            Page<WorkOrderViewPo> resultPage = workOrderViewService.page(page, wrapper);
            return R.ok(resultPage, "查询成功");
        } catch (Exception e) {
            log.error("查询工单列表失败", e);
            return R.fail("查询工单列表失败: " + e.getMessage());
        }
    }

    @Override
    public R<WorkOrderViewPo> getById(Long workOrderId) {
        try {
            WorkOrderViewPo workOrder = workOrderViewService.getById(workOrderId);
            if (workOrder != null) {
                return R.ok(workOrder, "查询成功");
            } else {
                return R.fail("工单不存在");
            }
        } catch (Exception e) {
            log.error("查询工单详情失败, workOrderId={}", workOrderId, e);
            return R.fail("查询工单详情失败: " + e.getMessage());
        }
    }

    @Override
    public R<Page<WorkOrderViewPo>> getByStatus(Page<WorkOrderViewPo> page, String status) {
        try {
            // TODO: 实现按状态分页查询逻辑
            // 这里需要根据实际的查询服务实现
            return R.ok(new Page<>(), "查询成功");
        } catch (Exception e) {
            log.error("按状态查询工单失败, status={}", status, e);
            return R.fail("按状态查询工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> update(Long workOrderId, CreateWorkOrderRequest request) {
        try {

            // 将字符串类型的工单类型转换为枚举
            WorkOrderTypeEnum workOrderTypeEnum = EnumUtil.getBy(
                    WorkOrderTypeEnum.class,
                    e -> request.getWorkOrderType().equals(e.getKey())
            );

            if (workOrderTypeEnum == null) {
                return R.fail("无效的工单类型: " + request.getWorkOrderType());
            }

            UpdateWorkOrderCommand command = new UpdateWorkOrderCommand(
                    workOrderId,
                    request.getWorkOrderCode(),
                    request.getProductId(),
                    request.getPlannedQuantity(),
                    request.getRouteId(),
                    request.getProductionLineId(),
                    workOrderTypeEnum,
                    request.getOriginalWorkOrderId(),
                    request.getPlannedStartTime(),
                    request.getPlannedEndTime(),
                    request.getRemarks()
            );

            CommandResult<Void> result = updateHandler.handle(command);

            if (result.success()) {
                // 更新读模型
                WorkOrderViewPo viewEntity = workOrderViewService.getById(workOrderId);
                if (viewEntity != null) {
                    // 查询相关名称信息
                    String productCode = null;
                    String productName = null;
                    if (request.getProductId() != null) {
                        MaterialViewPo material = materialViewService.getById(request.getProductId());
                        if (material != null) {
                            productCode = material.getMaterialCode();
                            productName = material.getMaterialName();
                        }
                    }

                    String routeCode = null;
                    String routeName = null;
                    if (request.getRouteId() != null) {
                        RouteViewPo route = routeViewService.getById(request.getRouteId());
                        if (route != null) {
                            routeCode = route.getRouteCode();
                            routeName = route.getRouteName();
                        }
                    }

                    String productionLineCode = null;
                    String productionLineName = null;
                    if (request.getProductionLineId() != null) {
                        ProductionLineBasicViewPo productionLine = productionLineViewService.getById(request.getProductionLineId());
                        if (productionLine != null) {
                            productionLineCode = productionLine.getLineCode();
                            productionLineName = productionLine.getLineName();
                        }
                    }

                    // 更新字段
                    viewEntity.setWorkOrderCode(request.getWorkOrderCode());
                    viewEntity.setWorkOrderType(request.getWorkOrderType());
                    viewEntity.setProductId(request.getProductId());
                    viewEntity.setProductCode(productCode);
                    viewEntity.setProductName(productName);
                    viewEntity.setRouteId(request.getRouteId());
                    viewEntity.setRouteCode(routeCode);
                    viewEntity.setRouteName(routeName);
                    viewEntity.setProductionLineId(request.getProductionLineId());
                    viewEntity.setProductionLineCode(productionLineCode);
                    viewEntity.setProductionLineName(productionLineName);
                    viewEntity.setPlannedQuantity(request.getPlannedQuantity());
                    viewEntity.setPlannedStartTime(request.getPlannedStartTime());
                    viewEntity.setPlannedEndTime(request.getPlannedEndTime());
                    viewEntity.setRemarks(request.getRemarks());
                    workOrderViewService.updateById(viewEntity);
                }
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("更新工单失败, workOrderId={}", workOrderId, e);
            return R.fail("更新工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> delete(Long workOrderId) {
        try {
            DeleteWorkOrderCommand command = new DeleteWorkOrderCommand(workOrderId);

            CommandResult<Void> result = deleteHandler.handle(command);

            if (result.success()) {
                // 删除读模型
                workOrderViewService.removeById(workOrderId);
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("删除工单失败, workOrderId={}", workOrderId, e);
            return R.fail("删除工单失败: " + e.getMessage());
        }
    }

    @Override
    public R<Void> batchDelete(List<Long> ids) {
        try {
            for (Long id : ids) {
                DeleteWorkOrderCommand command = new DeleteWorkOrderCommand(id);
                CommandResult<Void> result = deleteHandler.handle(command);
                if (result.success()) {
                    // 删除读模型
                    workOrderViewService.removeById(id);
                }
            }
            return R.ok();
        } catch (Exception e) {
            log.error("批量删除工单失败, ids={}", ids, e);
            return R.fail("批量删除工单失败: " + e.getMessage());
        }
    }

    @Override
    public List<WorkOrderOptionVo> getAvailableWorkOrders() {

        // 查询已下达或进行中的工单
        MPJLambdaWrapper<WorkOrderViewPo> wrapper = new MPJLambdaWrapper<>();
        wrapper.eq(WorkOrderViewPo::getStatus, WorkOrderStatusEnum.RELEASED.getKey());

        List<WorkOrderOptionVo> workOrders = workOrderViewService.selectJoinList(WorkOrderOptionVo.class, wrapper);
        return workOrders;
    }

}